﻿// -----------------------------------------------------------------------
// <copyright file="ArgumentHelper.cs" company="FastNET Services">
//     Copyright (c) 2008-2009. All Rights Reserved.
// </copyright>
// <license>
//     GPLv2
// </license>
// <warranty>
//     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
//     BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
//     DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </warranty>
// -----------------------------------------------------------------------
#region Usings

using System;
using System.Collections.Generic;

#endregion

namespace GateShift.Servers.GameServer.HelperClasses
{
    /// <summary>
    /// General class to help with argument processing
    /// </summary>
    public static class ArgumentHelper
    {
        /// <summary>
        /// Processes the arguments passed in from the command line and returns whether or 
        /// not the program should continue running after processing them
        /// </summary>
        /// <param name="arguments">string array of all arguments</param>
        /// <returns>Enumerable list of actions to be performed</returns>
        public static List<ArgumentAction> ProcessArguments(string[] arguments)
        {
            // Queue makes it easier to process one at a time
            Queue<string> items = new Queue<string>(arguments);
            List<ArgumentAction> returnValue = new List<ArgumentAction>();

            // Continue while our queue has items
            while (items.Count > 0)
            {
                // Get the next item
                string currentItem = items.Dequeue().ToLower();

                // Decide what to do with the item
                switch (currentItem)
                {
                    // Console Mode
                    case "--console":
                    case "-c":
                        if (!returnValue.Contains(ArgumentAction.ConsoleMode))
                        {
                            returnValue.Add(ArgumentAction.ConsoleMode);
                        }

                        break;

                    // Help
                    case "--help":
                    case "-?":
                    case "-h":
                        if (!returnValue.Contains(ArgumentAction.PrintHelp))
                        {
                            returnValue.Add(ArgumentAction.PrintHelp);
                        }

                        break;

                    // Anything not expected should result in a invalid action
                    default:
                        if (!returnValue.Contains(ArgumentAction.InvalidArgument))
                        {
                            returnValue.Add(ArgumentAction.InvalidArgument);
                        }

                        break;
                }
            }

            return returnValue;
        }

        /// <summary>
        /// Prints the help text for the program
        /// </summary>
        public static void PrintHelp()
        {
            Console.WriteLine("Application: {0}", SystemGlobals.AssemblyInfo.Title);
            Console.WriteLine("Product: {0}", SystemGlobals.AssemblyInfo.Product);
            Console.WriteLine("Version: {0}", SystemGlobals.AssemblyInfo.AssemblyVersion);
            Console.WriteLine();
            Console.WriteLine(SystemGlobals.AssemblyInfo.Copyright);
            Console.WriteLine();
            Console.WriteLine("   {0}", "--console, -c");
            Console.WriteLine("      {0}", "Tells the application to run in console mode for debugging and troubleshooting");
            Console.WriteLine();
            Console.WriteLine("   {0}", "--help, -h, -?");
            Console.WriteLine("      {0}", "Shows this help text for the application");
        }

        /// <summary>
        /// Takes a single argument string and parses it into argument components. As part of the split, we combine arguments with ".
        /// </summary>
        /// <param name="argumentString">string to split into argument components</param>
        /// <returns>List of Strings with all the argument components</returns>
        public static List<string> SplitArguments(string argumentString)
        {
            string[] rawSplit = argumentString.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            List<string> returnValue = new List<string>();

            string argument = string.Empty;
            bool isCombining = false;

            // Loop through all splits. We are going looking for " to group by
            foreach (string item in rawSplit)
            {
                // Add to our current argument
                argument += " ";
                argument += item;
                argument = argument.Trim();

                // If we are already combining, we want to look for the ending "
                if (isCombining)
                {
                    if (item.IndexOf('\"') > -1)
                    {
                        // We found one so now we add it to the returned arguments (" removed)
                        // and we set the isCombining back to false and empty the builder string
                        returnValue.Add(argument.Replace("\"", string.Empty));
                        isCombining = false;
                        argument = string.Empty;
                    }
                }
                else
                {
                    // Does this split contain a " that means we need to group stuff in between?
                    if (item.IndexOf('\"') > -1)
                    {
                        // Is the second " in this set?
                        if (item.IndexOf('\"', item.IndexOf('\"') + 1) > -1)
                        {
                            // If not then just add the argument and continue on
                            returnValue.Add(argument.Replace("\"", string.Empty));
                            argument = string.Empty;
                        }
                        else
                        {
                            isCombining = true;
                        }
                    }
                    else
                    {
                        // If not then just add the argument and continue on
                        returnValue.Add(argument.Replace("\"", string.Empty));
                        argument = string.Empty;
                    }
                }
            }

            // Is there anything left over? This could happen if they forgot to close a " somewhere
            if (!string.IsNullOrEmpty(argument))
            {
                returnValue.Add(argument.Replace("\"", string.Empty));
            }

            // Return our list
            return returnValue;
        }
    }
}